package com.elegant.code.aop.local;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 同步锁 AOP
 * 创建者	张志朋
 * 创建时间	2015年6月3日
 * @transaction 中  order 大小的说明
 * https://docs.spring.io/spring/docs/4.3.14.RELEASE/spring-framework-reference/htmlsingle/#transaction-declarative-annotations
 * https://docs.spring.io/spring/docs/4.3.14.RELEASE/javadoc-api/
 */
@Component
@Scope
@Aspect
@Order(1)//order越小越先执行，先执行的后结束，保证锁的有效性
public class LocalLockAspect {
	//并发下，lock是单例的
	private static  Lock lock = new ReentrantLock(true);//互斥锁 参数默认false，不公平锁
	@Pointcut("@annotation(com.elegant.code.aop.local.LocalLock)")
	public void lockAspect() {}
    @Around("lockAspect()")
    public  Object around(ProceedingJoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		long waitTime = method.getAnnotation(LocalLock.class).waitTime();
		Object obj = null;
		try {
			lock.tryLock(waitTime, TimeUnit.SECONDS);
			obj = joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
			throw new RuntimeException();       
		} finally{
			lock.unlock();
		}
    	return obj;
    } 
}
